package com.palmwindActivity.app;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
import java.util.concurrent.ThreadPoolExecutor;

import com.palmwindActivity.proto.ProtoBuf;
import com.palmwindActivity.proto.ProtoBufUtil;

public abstract class AbstractServiceProxy implements IJobNotifier{
	
	protected ThreadPoolExecutor threadPool;
	protected IServiceProxyListener serverListener;
	protected CommJob commJob;
	protected int status;
	protected String errMsg;
	public AbstractServiceProxy(ThreadPoolExecutor threadpool, IServiceProxyListener serverListener)
	{
		this.threadPool = threadpool;
		this.serverListener = serverListener;
	}
	
	protected Vector<ProtoBuf> createProtoBufReq(RequestParam requestItem)
    {
		Vector<ProtoBuf> request = new Vector<ProtoBuf>();
		if(requestItem.params != null && requestItem.params.size() > 0 )
		{
			addRequestArgs(request, requestItem);
		}
		return request;
    }	
	
	protected abstract void addRequestArgs(Vector<ProtoBuf> request, RequestParam requestItem);
	
	protected void sendData(Vector<ProtoBuf> requestVector, String actionId, int timeOut, int retryTimes)
	{
		byte[] data = ProtoBufUtil.listToByteArray(requestVector);
		commJob = new CommJob(0, actionId, timeOut, retryTimes, this);
		commJob.setData(data);
		this.threadPool.execute(commJob);
	}
	
	protected abstract void handleResponse(ProtoBuf[] response);
	
	public void notifyStart()
	{
		
	}
	
	public void notifyEnd()
	{
		if (commJob.getStatus() == ICommConstants.NETWORK_SUCCESS) {
			byte[] response = commJob.getResponse();
			ProtoBuf[] protoBuf = ProtoBufUtil.toBufArray(response);
			handleResponse(protoBuf);
			if(status == ICommConstants.NETWORK_PARSER_ERROR)
			{
				this.serverListener.networkError(status,commJob.getTag(), "Parser Error", this);
			}
			else
			{
				this.serverListener.networkFinished(commJob.getStatus(), commJob.getTag(), this);
			}
		}
		else
		{
			this.serverListener.networkError(commJob.getStatus(), commJob.getTag(), commJob.getErrorMsg(), this);
		}
	}
}

class CommJob extends AbstractJob
{
	protected int timeOut;
	protected int retryTimes;
	protected String errorMsg;
	protected byte data[];
	protected byte response[];
	protected int status = ICommConstants.NETWORK_NO_ACTION;
	
	public CommJob(int id, String tag, int timeOut, int retryTimes, IJobNotifier listener)
	{
		super(id, tag, listener);
	}

	public void setData(byte[] data) {
		this.data = data;
	}

	protected void executeJob(){

		if (AbstractCommManager.instance != null) {
			try {
				AbstractCommManager.instance.openConnection();
				OutputStream output = AbstractCommManager.instance
						.getOutStream();
				if (output != null) {

					output.write(data);
					output.flush();

					InputStream inputStream = AbstractCommManager.instance
							.getInputStream();
					long startTime = System.currentTimeMillis();
					while(inputStream.available() == 0)
					{
						try {
							Thread.sleep(200);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						long duration = System.currentTimeMillis() - startTime;
						if(duration > 10000)
						{
							break;
						}
							
					}
					int size = inputStream.available();
					System.out.println("size is :" + size);
					if (size > 0) {
						response = new byte[size];
						inputStream.read(response);
						this.status = ICommConstants.NETWORK_SUCCESS;
					}else
					{
						this.status = ICommConstants.NETWORK_FAIL;
					}

				} else {
					this.status = ICommConstants.NETWORK_FAIL;
					errorMsg = AbstractCommManager.instance.getErrorMsg();
				}
			} catch (IOException e) {
				this.status = ICommConstants.NETWORK_FAIL;
				errorMsg = e.getMessage();
			}
			finally
			{
				try {
					AbstractCommManager.instance.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		} else {

			this.status = ICommConstants.NETWORK_FAIL;
			errorMsg = "No socket connection";
		}
	}
			
//		else
//		{
//			this.status = ICommConstants.NETWORK_FAIL;
//			errorMsg = "No socket connection";
//		}
//		
//	}
	
	public String getErrorMsg()
	{
		return errorMsg;
	}
	
	public int getStatus()
	{
		return status;
	}
	
	public byte[] getResponse()
	{
		return response;
	}
}